package cn.wolfcode.web.config;

import cn.wolfcode.common.web.resolver.UserInfoMethodArgumentResolver;
import cn.wolfcode.common.web.interceptor.FeignRequestInterceptor;
import cn.wolfcode.common.web.interceptor.RequireLoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.async.TimeoutCallableProcessingInterceptor;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@EnableConfigurationProperties(ServletThreadPoolExecutorProperties.class)
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private ServletThreadPoolExecutorProperties servletThreadPoolExecutorProperties;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 注册自定义Servlet异步请求线程池
     * @return ThreadPoolTaskExecutor Spring提供的线程池对象
     */
    @Bean
    public ThreadPoolTaskExecutor servletThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(servletThreadPoolExecutorProperties.getThread().getCorePoolSize());
        //配置最大线程数
        executor.setMaxPoolSize(servletThreadPoolExecutorProperties.getThread().getMaxPoolSize());
        //配置队列线程的存活时间
        executor.setKeepAliveSeconds(servletThreadPoolExecutorProperties.getThread().getKeepAliveSeconds());
        //配置队列大小
        executor.setQueueCapacity(servletThreadPoolExecutorProperties.getThread().getQueueCapacity());
        //配置线程池中的线程名前缀
        executor.setThreadNamePrefix(servletThreadPoolExecutorProperties.getThread().getNamePrefix());
        return executor;
    }

    /**
     * 注册Servlet异步请求超时处理拦截器
     * @return TimeoutCallableProcessingInterceptor
     */
    @Bean
    public TimeoutCallableProcessingInterceptor timeoutCallableProcessingInterceptor() {
        return new TimeoutCallableProcessingInterceptor();
    }

    /**
     * 为Servlet异步请求配置线程池，超时时间，超时处理拦截器
     * @param configurer
     */
    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        //配置超时时间：ms
        configurer.setDefaultTimeout(servletThreadPoolExecutorProperties.getHandle().getTimeout());
        //配置请求线程池
        configurer.setTaskExecutor(servletThreadPoolTaskExecutor());
        //配置超时处理拦截器
//        configurer.registerCallableInterceptors(timeoutCallableProcessingInterceptor());
    }

    @Bean
    public RequireLoginInterceptor requireLoginInterceptor() {
        return new RequireLoginInterceptor(redisTemplate);
    }

    @Bean
    public FeignRequestInterceptor feignRequestInterceptor() {
        return new FeignRequestInterceptor();
    }

    @Bean
    public UserInfoMethodArgumentResolver userInfoMethodArgumentResolver() {
        return new UserInfoMethodArgumentResolver(redisTemplate);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(requireLoginInterceptor())
                .addPathPatterns("/**");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(userInfoMethodArgumentResolver());
    }
}
